package com.krtech.wecard.framework.ext.satoken;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.krtech.wecard.framework.exception.BusinessException;
import com.krtech.wecard.module.sys.entity.SysKeyValue;
import com.krtech.wecard.module.sys.entity.SysUser;
import com.krtech.wecard.module.sys.enums.SysEnums;
import com.krtech.wecard.module.sys.service.SysKeyValueService;
import com.krtech.wecard.module.sys.service.SysUserService;
import com.krtech.wecard.utils.IP2CityUtil;
import com.krtech.wecard.utils.http.HttpServletRequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 自定义侦听器的实现
 */
@Component
@Slf4j
public class MySaTokenListener implements SaTokenListener {
    public static final List<OnlineUser> ONLINE_USERS = new CopyOnWriteArrayList<>();

    @Value("${sa-token.timeout}")
    private int timeout;

    @Autowired
    SysUserService sysUserService;

    @Autowired
    private SysKeyValueService keyValueService;

    @PostConstruct
    public void init() {
        initRefreshThread();
    }

    /**
     * 每次登录时触发
     */
    @Override
    public void doLogin(String loginType, Object loginId, SaLoginModel loginModel) {
        UserAgent requestUserAgent = HttpServletRequestUtil.getRequestUserAgent();
        String cityInfo = IP2CityUtil.getCityInfo(HttpServletRequestUtil.getRemoteIP());
        String[] split = cityInfo.split("\\|");
//        ONLINE_USERS.add(OnlineUser.builder()
//                .ip(HttpServletRequestUtil.getRemoteIP())
//                .city(StrUtil.format("{}.{}.{}", split[0], split[2], split[3]))
//                .loginTime(new Date())
//                .os(requestUserAgent.getOs().getName())
//                .userId((Long.parseLong(loginId.toString())))
//                .tokenValue(StpUtil.getTokenValue())
////                .nickName(sysUserService.getById((Long) loginId).getNickName())
//                .browser(requestUserAgent.getBrowser().getName()).build());
//        log.info("user doLogin,useId:{},token:{}", loginId, StpUtil.getTokenValue());

        //登陆时候保存数据到现在user中
        SysUser user = sysUserService.getById(loginId.toString());

        if (user != null){
            SaManager.getSaTokenDao().set("userInfo:"+loginId, JSONUtil.toJsonStr(user),timeout);
        }

        //将超级管理员放进缓存
        //判断这个人 是否拥有超级管理员权限，在keyvalue中查询超级管理员的id
        SysKeyValue superAdmin = keyValueService.getOne(new QueryWrapper<SysKeyValue>()
                .eq(SysKeyValue.COL_SYS_NAME, SysEnums.SUPER_ADMIN));
        if (superAdmin == null){
            throw new BusinessException("系统超级管理员配置丢失，请联系负责人");
        }
        SaManager.getSaTokenDao().set("SUPER_ADMIN", superAdmin.getSysValue(),timeout);
    }

    /**
     * 每次注销时触发
     */
    @Override
    public void doLogout(String loginType, Object loginId, String tokenValue) {
        // ...
//        if (ONLINE_USERS.size() > 0){
//            ONLINE_USERS.removeIf(onlineUser ->
//                    onlineUser.getTokenValue().equals(tokenValue)
//            );
//            log.info("user doLogout,useId:{},token:{}", loginId, tokenValue);
//
//        }
        SaManager.getSaTokenDao().delete("wecard:login:token:"+tokenValue);

    }

    /**
     * 每次被踢下线时触发
     *
     * @param loginType  账号类别
     * @param loginId    账号id
     * @param tokenValue token值
     */
    @Override
    public void doKickout(String loginType, Object loginId, String tokenValue) {
        ONLINE_USERS.removeIf(onlineUser ->
                onlineUser.getTokenValue().equals(tokenValue)
        );
        log.info("user doLogoutByLoginId,useId:{},token:{}", loginId, tokenValue);
    }

    /**
     * 每次被顶下线时触发
     *
     * @param loginType  账号类别
     * @param loginId    账号id
     * @param tokenValue token值
     */
    @Override
    public void doReplaced(String loginType, Object loginId, String tokenValue) {
        ONLINE_USERS.removeIf(onlineUser ->
                onlineUser.getTokenValue().equals(tokenValue)
        );
        log.info("user doReplaced,useId:{},token:{}", loginId, tokenValue);
    }

    /**
     * 每次被封禁时触发
     */
    @Override
    public void doDisable(String loginType, Object loginId, long disableTime) {
        // ... 
    }

    /**
     * 每次被解封时触发
     */
    @Override
    public void doUntieDisable(String loginType, Object loginId) {
        // ... 
    }

    /**
     * 每次创建Session时触发
     */
    @Override
    public void doCreateSession(String id) {
        // ...
        log.info("user doCreateSession,id:{}", id);
    }

    /**
     * 每次注销Session时触发
     */
    @Override
    public void doLogoutSession(String id) {
        // ...
        log.info("user doLogoutSession,id:{}", id);
    }
    // --------------------- 定时清理过期数据

    /**
     * 执行数据清理的线程
     */
    public Thread refreshThread;

    /**
     * 是否继续执行数据清理的线程标记
     */
    public boolean refreshFlag;

    /**
     * 初始化定时任务
     */
    public void initRefreshThread() {

//        // 如果配置了<=0的值，则不启动定时清理
//        if (SaManager.getConfig().getDataRefreshPeriod() <= 0) {
//            return;
//        }
//        // 启动定时刷新
//        this.refreshFlag = true;
//        this.refreshThread = new Thread(() -> {
//            for (; ; ) {
////                log.info("定时清理过期会话开始。间隔：{}s,在线人数：{}", SaManager.getConfig().getDataRefreshPeriod() + 5, ONLINE_USERS.size());
//                try {
//                    try {
//                        // 如果已经被标记为结束
//                        if (refreshFlag == false) {
//                            return;
//                        }
//                        long start = System.currentTimeMillis();
//                        ONLINE_USERS.removeIf(onlineUser -> {
//                            long timeout = StpUtil.stpLogic.getTokenActivityTimeoutByToken(onlineUser.getTokenValue());
//                            if (timeout == SaTokenDao.NOT_VALUE_EXPIRE) {
//                                return true;
//                            }
//                            return false;
//                        });
////                        log.info("定时清理过期会话结束，在线人数：{},耗时：{}ms", ONLINE_USERS.size(), System.currentTimeMillis() - start);
//
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                    // 休眠N秒
//                    int dataRefreshPeriod = SaManager.getConfig().getDataRefreshPeriod();
//                    if (dataRefreshPeriod <= 0) {
//                        dataRefreshPeriod = 1;
//                    }
//                    dataRefreshPeriod = dataRefreshPeriod + 5;
//                    Thread.sleep(dataRefreshPeriod * 1000);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        });
//        refreshThread.start();
    }

}
